package me.keiwu.user.service.impl;

import me.keiwu.pub.data.ConfigType;
import me.keiwu.pub.data.ResponseV2;
import me.keiwu.pub.data.config.ExploreConfigBean;
import me.keiwu.pub.data.service.UserInfoBean;
import me.keiwu.pub.util.AreaUtil;
import me.keiwu.pub.util.CacheUtil;
import me.keiwu.pub.util.DateUtil;
import me.keiwu.user.dao.UserLbsDao;
import me.keiwu.user.domain.User;
import me.keiwu.user.domain.UserLbs;
import me.keiwu.user.service.UserLbsService;
import me.keiwu.user.service.UserService;
import me.keiwu.user.util.ExceptionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by kei on 31/01/2018.
 */
@Service
@Transactional
public class UserLbsServiceImpl implements UserLbsService {



    @Autowired
    private UserLbsDao userLbsDao;
    @Autowired
    private UserService userService;
    @Autowired
    private CacheUtil cacheUtil;
    @Autowired
    private ExceptionUtil exceptionUtil;


    @Override
    public UserLbs updateLbs(Long userId, Double latitude, Double longitude, Long cityCode, String cityName) {
        User user = userService.getUserById(userId);
        if (user == null) return null;
        user.setLbsCityName(cityName);
        userService.save(user);

        UserLbs ul = new UserLbs();
        ul.setUserId(userId);
        ul.setLatitude(latitude);
        ul.setLongitude(longitude);
        // 区
        ul.setDistrict(AreaUtil.getDistrict(cityCode));
        // 市
        ul.setCity(AreaUtil.getCity(cityCode));
        // 省
        ul.setProvince(AreaUtil.getProvince(cityCode));
        ul.setUpdateTime(DateUtil.getUnixTime());
        userLbsDao.save(ul);
        return ul;
    }


//    @Override
//    public Page<UserInfoBean> fetchNearUser(Long cityCode, Page<UserInfoBean> page) {
//        List<UserLbs> userLbsList = new ArrayList<>();
//        int offset = page.getPage() * page.getSize();
//        int size = page.getSize();
//
//        int district = AreaUtil.getDistrict(cityCode);
//        int districtCount = userLbsDao.countByDistrict(district);
//        if (districtCount >= offset + 1) {
//            List<UserLbs> ull = userLbsDao.findAllByDistrict(district, offset, size);
//            userLbsList.addAll(ull);
//            size -= ull.size();
//        }
//        offset -= districtCount;
//        offset = offset < 0 ? 0 : offset;
//        if (size <= 0) return this.doFetchNearUser(page, userLbsList);
//
//        int city = AreaUtil.getCity(cityCode);
//        int cityCount = userLbsDao.countByCityNotInDistrict(city, district);
//        if (cityCount >= offset + 1) {
//            List<UserLbs> ull = userLbsDao.findAllByCityNotInDistrict(city, district, offset, size);
//            userLbsList.addAll(ull);
//            size -= ull.size();
//        }
//        offset -= cityCount;
//        offset = offset < 0 ? 0 : offset;
//        if (size <= 0) return this.doFetchNearUser(page, userLbsList);
//
//
//        int province = AreaUtil.getProvince(cityCode);
//        int provinceCount = userLbsDao.countByProvinceNotInCity(province, city);
//        if (provinceCount >= offset + 1) {
//            List<UserLbs> ull = userLbsDao.findAllByProvinceNotInCity(province, city, offset, size);
//            userLbsList.addAll(ull);
//        }
//        return this.doFetchNearUser(page, userLbsList);
//    }
//
//    private Page<UserInfoBean> doFetchNearUser(Page<UserInfoBean> page, List<UserLbs> userLbsList) {
//        List<UserInfoBean> list = new ArrayList<>();
//        userLbsList.forEach(ul -> {
//            list.add(userService.getUserInfo(ul.getUserId(), false));
//        });
//        page.setContent(list);
//        page.setTotal(userLbsDao.countAll());
//        return page;
//    }



    @Override
    public List<UserInfoBean> fetchNearUserRandom(Long userId, Long cityCode, int size, boolean refresh) {
        List<Long> refreshIds = cacheUtil.getRefreshUsers(userId);
        if (!refresh) {
            // 获取当天已经刷新过的列表，直接返回
            if (refreshIds.size() > 0) {
                List<UserInfoBean> list = new ArrayList<>();
                refreshIds.forEach(id -> {
                    UserInfoBean bean = userService.getUserInfo(id);
                    if (bean != null) list.add(bean);
                });
                return list;
            }
        }
        // 过滤自己
        refreshIds.add(userId);

        // 先刷区的
        int district = AreaUtil.getDistrict(cityCode);
        List<UserLbs> lbsList = new ArrayList<>();
        List<UserLbs> districtList = userLbsDao.findAllByDistrictRand(district, refreshIds, size);
        lbsList.addAll(districtList);
        size -= districtList.size();
        if (size <= 0) return this.doFetchNearUserRand(userId, lbsList);
        districtList.forEach(lbs -> refreshIds.add(lbs.getUserId()));

        // 再刷市的
        int city = AreaUtil.getCity(cityCode);
        List<UserLbs> cityList = userLbsDao.findAllByCityRand(city, refreshIds, size);
        lbsList.addAll(cityList);
        size -= cityList.size();
        if (size <= 0) return this.doFetchNearUserRand(userId, lbsList);
        cityList.forEach(lbs -> refreshIds.add(lbs.getUserId()));

        // 最后刷省的
        int province = AreaUtil.getProvince(cityCode);
        List<UserLbs> provinceList = userLbsDao.findAllByProvinceRand(province, refreshIds, size);
        lbsList.addAll(provinceList);
        return this.doFetchNearUserRand(userId, lbsList);
    }

    private List<UserInfoBean> doFetchNearUserRand(Long userId, List<UserLbs> userLbsList) {
        List<UserInfoBean> list = new ArrayList<>();
        List<Long> userIds = new ArrayList<>();
        userLbsList.forEach(ul -> {
            if (!userId.equals(ul.getUserId())) {
                userIds.add(ul.getUserId());
                UserInfoBean bean = userService.getUserInfo(ul.getUserId());
                if (bean != null) list.add(bean);
            }
        });
        // 如果列表为空，则不扣金币（直接返回空列表）
        // 如果没有初始化，则不扣金币，然后保存初始化列表
        ExploreConfigBean config = cacheUtil.getConfig(ConfigType.EXPLORE_CONFIG, ExploreConfigBean.class);
        if (config == null) {
            exceptionUtil.logError(this.getClass(), "doFetchNearUserRand", "need explore config!");
            return Collections.emptyList();
        }

        if (list.size() > 0 && cacheUtil.getRefreshUsers(userId).size() <= 0) {
            // 记录刷新过用户
            cacheUtil.recordRefreshUsers(userId, userIds);
            return list;
        } else if (list.size() > 0 && userService.changeGold(userId, -Math.abs(config.getExploreCost()))) {
            // 记录刷新用户
            cacheUtil.recordRefreshUsers(userId, userIds);
            return list;
        }
        return Collections.emptyList();
    }





    public static void main(String[] args) {
        Long cityCode  = 110101017020L;
        System.out.println("区:" + AreaUtil.getDistrict(cityCode));
        System.out.println("市:" + AreaUtil.getCity(cityCode));
        System.out.println("省:" + AreaUtil.getProvince(cityCode));
    }

}
